#!/usr/bin/env python3
"""
DSL语法迁移脚本
自动将旧的DSL语法替换为新的标准语法

使用方法:
python scripts/migrate-dsl-syntax.py [目录路径]
"""

import os
import re
import sys
import yaml
from pathlib import Path
from typing import Dict, Any, List
import argparse
import logging

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class DSLSyntaxMigrator:
    """DSL语法迁移器"""
    
    def __init__(self):
        # 定义需要替换的语法映射
        self.syntax_replacements = {
            # 字段名称替换
            'fields:': 'attributes:',
            'relations:': 'associations:',
            'relationships:': 'associations:',
            'emits:': 'events:',
            
            # 属性格式替换 (正则表达式)
            r'(\s+)primary:\s*true': r'\1rules: [primary]',
            r'(\s+)unique:\s*true': r'\1rules: [unique]', 
            r'(\s+)required:\s*true': r'\1rules: [required]',
            r'(\s+)primary:\s*false': '',  # 移除false值
            r'(\s+)unique:\s*false': '',   # 移除false值
            r'(\s+)required:\s*false': '', # 移除false值
        }
        
        # 关系类型标准化
        self.relation_type_replacements = {
            'hasMany': 'one-to-many',
            'belongsTo': 'many-to-one',
            'hasOne': 'one-to-one',
            'belongsToMany': 'many-to-many',
            'oneToOne': 'one-to-one',
            'oneToMany': 'one-to-many',
            'manyToOne': 'many-to-one',
            'manyToMany': 'many-to-many'
        }
        
        self.processed_files = []
        self.error_files = []
        
    def migrate_file(self, file_path: Path) -> bool:
        """迁移单个文件"""
        try:
            logger.info(f"正在处理文件: {file_path}")
            
            # 读取文件内容
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            original_content = content
            
            # 应用基本语法替换
            content = self._apply_basic_replacements(content)
            
            # 应用关系类型替换
            content = self._apply_relation_type_replacements(content)
            
            # 处理复杂的验证规则格式
            content = self._migrate_validation_rules(content)
            
            # 如果内容有变化，写回文件
            if content != original_content:
                # 创建备份
                backup_path = file_path.with_suffix(file_path.suffix + '.backup')
                with open(backup_path, 'w', encoding='utf-8') as f:
                    f.write(original_content)
                logger.info(f"已创建备份: {backup_path}")
                
                # 写入新内容
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(content)
                
                logger.info(f"✅ 已更新文件: {file_path}")
                self.processed_files.append(str(file_path))
                return True
            else:
                logger.info(f"⏭️  文件无需更新: {file_path}")
                return True
                
        except Exception as e:
            logger.error(f"❌ 处理文件失败 {file_path}: {str(e)}")
            self.error_files.append(str(file_path))
            return False
    
    def _apply_basic_replacements(self, content: str) -> str:
        """应用基本语法替换"""
        for old_syntax, new_syntax in self.syntax_replacements.items():
            if old_syntax.startswith('r\''):
                # 正则表达式替换
                pattern = old_syntax[2:-1]  # 移除 r' 和 '
                content = re.sub(pattern, new_syntax, content, flags=re.MULTILINE)
            else:
                # 简单字符串替换
                content = content.replace(old_syntax, new_syntax)
        
        return content
    
    def _apply_relation_type_replacements(self, content: str) -> str:
        """应用关系类型替换"""
        for old_type, new_type in self.relation_type_replacements.items():
            # 替换 type: 后面的关系类型
            pattern = f'type:\\s*{old_type}'
            replacement = f'type: {new_type}'
            content = re.sub(pattern, replacement, content)
        
        return content
    
    def _migrate_validation_rules(self, content: str) -> str:
        """迁移验证规则格式"""
        lines = content.split('\n')
        result_lines = []
        i = 0
        
        while i < len(lines):
            line = lines[i]
            
            # 检查是否是属性定义行
            if re.match(r'^(\s+)(\w+):\s*$', line):
                indent_match = re.match(r'^(\s+)', line)
                if indent_match:
                    base_indent = indent_match.group(1)
                    attr_indent = base_indent + '  '
                    
                    # 收集该属性的所有子属性
                    attr_lines = [line]
                    j = i + 1
                    
                    while j < len(lines) and (lines[j].strip() == '' or lines[j].startswith(attr_indent)):
                        attr_lines.append(lines[j])
                        j += 1
                    
                    # 处理属性块
                    processed_block = self._process_attribute_block(attr_lines, base_indent)
                    result_lines.extend(processed_block)
                    
                    i = j
                    continue
            
            result_lines.append(line)
            i += 1
        
        return '\n'.join(result_lines)
    
    def _process_attribute_block(self, attr_lines: List[str], base_indent: str) -> List[str]:
        """处理单个属性块，合并验证规则"""
        if not attr_lines:
            return attr_lines
        
        attr_name_line = attr_lines[0]
        attr_indent = base_indent + '  '
        
        # 解析属性信息
        type_line = None
        rules = []
        other_lines = []
        
        for line in attr_lines[1:]:
            stripped = line.strip()
            if not stripped:
                other_lines.append(line)
                continue
                
            if stripped.startswith('type:'):
                type_line = line
            elif stripped.startswith('rules:'):
                # 已经是rules格式，保持不变
                other_lines.append(line)
            elif stripped in ['required: true', 'unique: true', 'primary: true']:
                rule_name = stripped.split(':')[0]
                rules.append(rule_name)
            elif stripped.startswith('format:'):
                format_value = stripped.split(':', 1)[1].strip()
                rules.append(f'{{ format: {format_value} }}')
            else:
                other_lines.append(line)
        
        # 重新构建属性块
        result = [attr_name_line]
        
        if type_line:
            result.append(type_line)
        
        if rules:
            if len(rules) == 1:
                result.append(f'{attr_indent}rules: [{rules[0]}]')
            else:
                result.append(f'{attr_indent}rules: [{", ".join(rules)}]')
        
        result.extend(other_lines)
        
        return result
    
    def migrate_directory(self, directory: Path, pattern: str = "*.yml") -> None:
        """迁移目录下的所有文件"""
        logger.info(f"开始迁移目录: {directory}")
        
        if not directory.exists():
            logger.error(f"目录不存在: {directory}")
            return
        
        # 查找所有匹配的文件
        yaml_files = list(directory.rglob(pattern))
        yaml_files.extend(list(directory.rglob("*.yaml")))
        
        if not yaml_files:
            logger.warning(f"在目录 {directory} 中未找到YAML文件")
            return
        
        logger.info(f"找到 {len(yaml_files)} 个文件需要处理")
        
        # 处理每个文件
        for file_path in yaml_files:
            self.migrate_file(file_path)
    
    def print_summary(self) -> None:
        """打印迁移摘要"""
        print("\n" + "="*60)
        print("DSL语法迁移完成")
        print("="*60)
        print(f"✅ 成功处理文件: {len(self.processed_files)}")
        print(f"❌ 处理失败文件: {len(self.error_files)}")
        
        if self.processed_files:
            print("\n已处理的文件:")
            for file_path in self.processed_files:
                print(f"  - {file_path}")
        
        if self.error_files:
            print("\n处理失败的文件:")
            for file_path in self.error_files:
                print(f"  - {file_path}")
        
        print("\n💡 提示:")
        print("  - 原文件已备份为 .backup 后缀")
        print("  - 请运行测试验证迁移结果")
        print("  - 如有问题可从备份文件恢复")

def main():
    """主函数"""
    parser = argparse.ArgumentParser(description='DSL语法迁移工具')
    parser.add_argument('directory', nargs='?', default='.', 
                       help='要迁移的目录路径 (默认: 当前目录)')
    parser.add_argument('--pattern', default='*.yml', 
                       help='文件匹配模式 (默认: *.yml)')
    parser.add_argument('--dry-run', action='store_true',
                       help='预览模式，不实际修改文件')
    
    args = parser.parse_args()
    
    directory = Path(args.directory).resolve()
    
    print("DSL语法迁移工具")
    print("="*40)
    print(f"目标目录: {directory}")
    print(f"文件模式: {args.pattern}")
    print(f"预览模式: {'是' if args.dry_run else '否'}")
    print()
    
    if args.dry_run:
        print("⚠️  预览模式：将显示需要修改的文件，但不会实际修改")
        print()
    
    # 创建迁移器并执行迁移
    migrator = DSLSyntaxMigrator()
    
    if args.dry_run:
        # TODO: 实现预览模式
        print("预览模式暂未实现")
        return
    
    migrator.migrate_directory(directory, args.pattern)
    migrator.print_summary()

if __name__ == '__main__':
    main()